﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.ComponentModel;
using System.IO;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Pg.BioMedics.SDR.Web.Controls
{
    /// <summary>
    /// This web control allows voice recording directly from 
    /// computers microphone
    /// </summary>
    [ToolboxData("<{0}:VoiceRecorder runat=\"server\"/>")]
    [ToolboxItem(true)]
    public class VoiceRecorder : WebControl
    {
        #region Constants

        private const string ControlTemplateResource = "Pg.BioMedics.SDR.Web.Controls.VoiceRecorder.VoiceRecorder.template";
        private const string VoiceRecorderResource = "Pg.BioMedics.SDR.Web.Controls.VoiceRecorder.VoiceRecorder.swf";
        private const string ScriptResource = "Pg.BioMedics.SDR.Web.Controls.VoiceRecorder.VoiceRecorder.js";
        private const string IdTemplateKey = "{id}";
        private const string UrlTemplateKey = "{url}";
        private const string StreamUrlTemplateKey = "{streamUrl}";

        #endregion

        #region Fields

        private string streamAppName = "Voice";
        private int streamingPort = 1935;

        private string clientOnConnect;
        private string clientOnRecord;
        private string clientOnStop;
        private string clientOnError;
        private string clientOnPlay;

        #endregion

        #region Properties

        /// <summary>
        /// Gets / sets stream endpoint location
        /// </summary>
        public string StreamAppName
        {
            get
            {
                return this.streamAppName;
            }

            set
            {
                this.streamAppName = value;
            }
        }

        /// <summary>
        /// Gets / sets streaming port
        /// </summary>
        public int StreamingPort
        {
            get
            {
                return this.streamingPort;
            }

            set
            {
                this.streamingPort = value;
            }
        }

        /// <summary>
        /// Gets / sets client script handler for connect event
        /// </summary>
        public string ClientOnConnect
        {
            get
            {
                return this.clientOnConnect;
            }

            set
            {
                this.clientOnConnect = value;
            }
        }

        /// <summary>
        /// Gets / sets client script handler for record event
        /// </summary>
        public string ClientOnRecord
        {
            get
            {
                return this.clientOnRecord;
            }

            set
            {
                this.clientOnRecord = value;
            }
        }

        /// <summary>
        /// Gets / sets client script handler for stop event
        /// </summary>
        public string ClientOnStop
        {
            get
            {
                return this.clientOnStop;
            }

            set
            {
                clientOnStop = value;
            }
        }

        /// <summary>
        /// Gets / sets client script handler for error event
        /// </summary>
        public string ClientOnError
        {
            get
            {
                return this.clientOnError;
            }

            set
            {
                this.clientOnError = value;
            }
        }

        /// <summary>
        /// Gets / sets client script handler for play event
        /// </summary>
        public string ClientOnPlay
        {
            get
            {
                return this.clientOnPlay;
            }

            set
            {
                this.clientOnPlay = value;
            }
        }

        #endregion

        #region Overriden methods 

        protected override void CreateChildControls()
        {
            // load scripts
            ScriptManagerProxy scriptManagerProxy = new ScriptManagerProxy();
            scriptManagerProxy.Scripts.Add(new ScriptReference(ScriptResource, Assembly.GetExecutingAssembly().FullName));

            Controls.Add(scriptManagerProxy);

            // create object section with embedded flash
            ClientScriptManager clientScriptManager = Page.ClientScript;

            // load container panel
            Panel container = new Panel();
            container.CssClass = CssClass;

            Controls.Add(container);

            // content
            Literal literal = new Literal();
            literal.Text = GetControlTemplate().Replace(IdTemplateKey, ID)
                                               .Replace(UrlTemplateKey, clientScriptManager.GetWebResourceUrl(typeof(VoiceRecorder), VoiceRecorderResource))
                                               .Replace(StreamUrlTemplateKey, GetStreamUrl());
            container.Controls.Add(literal);
               
            // register startup script
            ScriptManager.RegisterStartupScript(this, typeof(Page), Guid.NewGuid().ToString(), BuildStartupScript(), true);       
        }

        #endregion

        #region Support methods

        private string GetControlTemplate()
        {
            using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(ControlTemplateResource))
            {
                using (StreamReader reader = new StreamReader(stream))
                {
                    return reader.ReadToEnd();
                }
            }
        }

        private string GetStreamUrl()
        {
            return String.Format("rtmp://{0}:{1}/{2}", Page.Request.Url.Host, 
                                                       this.streamingPort, 
                                                       this.streamAppName);
        }

        private string BuildStartupScript()
        {
            StringBuilder startupScript = new StringBuilder();
            if (!String.IsNullOrEmpty(this.clientOnConnect))
                startupScript.AppendLine("VoiceRecorder.onConnect = function() { {0} };".Replace("{0}", this.clientOnConnect));
            if (!String.IsNullOrEmpty(this.clientOnRecord))
                startupScript.AppendLine("VoiceRecorder.onRecord = function() { {0} };".Replace("{0}", this.clientOnRecord));
            if (!String.IsNullOrEmpty(this.clientOnStop))
                startupScript.AppendLine("VoiceRecorder.onStop = function(interval) { {0} };".Replace("{0}", this.clientOnStop));
            if (!String.IsNullOrEmpty(this.clientOnError))
                startupScript.AppendLine("VoiceRecorder.onError = function(code) { {0} };".Replace("{0}", this.clientOnError));
            if (!String.IsNullOrEmpty(this.clientOnPlay))
                startupScript.AppendLine("VoiceRecorder.onPlay = function() { {0} };".Replace("{0}", this.clientOnPlay));

            return startupScript.ToString();
        }

        #endregion
    }
}
